"""
MAESS备份系统API端点
提供备份和恢复相关的HTTP接口
"""

from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks
from fastapi.responses import JSONResponse
from typing import List, Dict, Any, Optional
from datetime import datetime

from loguru import logger
from core.backup.backup_manager import (
    get_backup_manager, create_backup as create_backup_manager,
    restore_backup as restore_backup_manager, list_available_backups
)
from core.backup.backup_scheduler import (
    get_backup_scheduler, trigger_backup as trigger_backup_scheduler,
    list_scheduled_jobs as list_scheduler_jobs
)
from utils.constants.backup_constants import (
    BackupType, BackupStatus, RestoreMode
)
from utils.exceptions.backup_exceptions import (
    BackupError, RestoreError, BackupNotFoundException,
    BackupInProgressError, RestoreInProgressError,
    InvalidBackupTypeError, InvalidRestoreModeError
)
from app.core.auth import require_admin

router = APIRouter(prefix="/api/backup", tags=["backup"])


@router.post("/create", dependencies=[Depends(require_admin)])
async def create_backup(
    backup_type: str = BackupType.FULL,
    background_tasks: BackgroundTasks = None
) -> Dict[str, Any]:
    """
    创建备份
    
    Args:
        backup_type: 备份类型 (full/database/redis/filesystem)
        background_tasks: FastAPI后台任务
    
    Returns:
        Dict: 备份信息
    """
    # 验证备份类型
    if backup_type not in [BackupType.FULL, BackupType.DATABASE, BackupType.REDIS, BackupType.FILESYSTEM]:
        raise HTTPException(status_code=400, detail=f"无效的备份类型: {backup_type}")
    
    try:
        # 检查是否已有备份在进行中
        manager = get_backup_manager()
        if backup_type in manager._active_backups:
            raise HTTPException(status_code=409, detail=f"{backup_type} 备份正在进行中，请稍后再试")
        
        # 触发备份
        if background_tasks:
            # 异步执行备份
            backup_id = await trigger_backup_scheduler(backup_type)
            return {
                "status": "started",
                "message": "备份已在后台开始执行",
                "backup_id": backup_id,
                "backup_type": backup_type,
                "timestamp": datetime.now().isoformat()
            }
        else:
            # 同步执行备份
            record = await create_backup_manager(backup_type)
            return record.to_dict()
            
    except InvalidBackupTypeError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except BackupInProgressError as e:
        raise HTTPException(status_code=409, detail=str(e))
    except Exception as e:
        logger.error(f"创建备份失败: {e}")
        raise HTTPException(status_code=500, detail=f"创建备份失败: {str(e)}")


@router.get("/list", dependencies=[Depends(require_admin)])
async def list_backups(
    backup_type: Optional[str] = None,
    limit: int = 50,
    offset: int = 0
) -> Dict[str, Any]:
    """
    列出所有备份
    
    Args:
        backup_type: 可选的备份类型过滤
        limit: 返回的最大记录数
        offset: 偏移量
    
    Returns:
        Dict: 备份列表和元数据
    """
    try:
        # 验证备份类型（如果提供）
        if backup_type and backup_type not in [BackupType.FULL, BackupType.DATABASE, BackupType.REDIS, BackupType.FILESYSTEM]:
            raise HTTPException(status_code=400, detail=f"无效的备份类型: {backup_type}")
        
        # 获取备份列表
        backups = await list_available_backups(backup_type)
        
        # 按时间倒序排序
        backups.sort(key=lambda x: x["created_at"], reverse=True)
        
        # 分页
        total = len(backups)
        paginated_backups = backups[offset:offset + limit]
        
        return {
            "total": total,
            "limit": limit,
            "offset": offset,
            "backups": paginated_backups
        }
        
    except Exception as e:
        logger.error(f"获取备份列表失败: {e}")
        raise HTTPException(status_code=500, detail=f"获取备份列表失败: {str(e)}")


@router.get("/info/{backup_id}", dependencies=[Depends(require_admin)])
async def get_backup_info(backup_id: str) -> Dict[str, Any]:
    """
    获取备份详情
    
    Args:
        backup_id: 备份ID
    
    Returns:
        Dict: 备份详细信息
    """
    try:
        manager = get_backup_manager()
        record = manager.get_backup_info(backup_id)
        
        if not record:
            raise HTTPException(status_code=404, detail=f"备份 {backup_id} 不存在")
        
        return record.to_dict()
        
    except BackupNotFoundException as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error(f"获取备份详情失败: {e}")
        raise HTTPException(status_code=500, detail=f"获取备份详情失败: {str(e)}")


@router.post("/restore", dependencies=[Depends(require_admin)])
async def restore_backup(
    backup_id: str,
    restore_mode: str = RestoreMode.FULL
) -> Dict[str, Any]:
    """
    恢复备份
    
    Args:
        backup_id: 备份ID
        restore_mode: 恢复模式 (full/database/redis/filesystem)
    
    Returns:
        Dict: 恢复结果
    """
    # 验证恢复模式
    if restore_mode not in [RestoreMode.FULL, RestoreMode.DATABASE, RestoreMode.REDIS, RestoreMode.FILESYSTEM]:
        raise HTTPException(status_code=400, detail=f"无效的恢复模式: {restore_mode}")
    
    try:
        # 执行恢复
        result = await restore_backup_manager(backup_id, restore_mode)
        return result
        
    except BackupNotFoundException as e:
        raise HTTPException(status_code=404, detail=str(e))
    except RestoreError as e:
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        logger.error(f"恢复备份失败: {e}")
        raise HTTPException(status_code=500, detail=f"恢复备份失败: {str(e)}")


@router.post("/delete/{backup_id}", dependencies=[Depends(require_admin)])
async def delete_backup(backup_id: str) -> Dict[str, Any]:
    """
    删除备份
    
    Args:
        backup_id: 备份ID
    
    Returns:
        Dict: 删除结果
    """
    try:
        manager = get_backup_manager()
        record = manager.get_backup_info(backup_id)
        
        if not record:
            raise HTTPException(status_code=404, detail=f"备份 {backup_id} 不存在")
        
        # 删除备份文件
        if record.path and os.path.exists(record.path):
            if os.path.isdir(record.path):
                shutil.rmtree(record.path)
            else:
                os.remove(record.path)
        
        # 从历史记录中移除
        manager._backup_history.remove(record)
        await manager._save_backup_history()
        
        logger.info(f"已删除备份: {backup_id}")
        
        return {
            "status": "success",
            "message": f"备份 {backup_id} 已成功删除",
            "backup_id": backup_id
        }
        
    except BackupNotFoundException as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error(f"删除备份失败: {e}")
        raise HTTPException(status_code=500, detail=f"删除备份失败: {str(e)}")


@router.get("/schedule/list", dependencies=[Depends(require_admin)])
async def list_schedules() -> Dict[str, Any]:
    """
    列出所有备份计划
    
    Returns:
        Dict: 计划任务列表
    """
    try:
        scheduler = get_backup_scheduler()
        jobs = scheduler.list_scheduled_jobs()
        
        return {
            "total": len(jobs),
            "jobs": jobs,
            "scheduler_status": scheduler.get_status()
        }
        
    except Exception as e:
        logger.error(f"获取备份计划失败: {e}")
        raise HTTPException(status_code=500, detail=f"获取备份计划失败: {str(e)}")


@router.post("/schedule/add", dependencies=[Depends(require_admin)])
async def add_schedule(
    backup_type: str,
    cron_expression: str
) -> Dict[str, Any]:
    """
    添加备份计划
    
    Args:
        backup_type: 备份类型
        cron_expression: Cron表达式，格式："分 时 日 月 周"
    
    Returns:
        Dict: 添加结果
    """
    # 验证备份类型
    if backup_type not in [BackupType.FULL, BackupType.DATABASE, BackupType.REDIS, BackupType.FILESYSTEM]:
        raise HTTPException(status_code=400, detail=f"无效的备份类型: {backup_type}")
    
    try:
        scheduler = get_backup_scheduler()
        success = scheduler.add_backup_job(backup_type, cron_expression)
        
        if not success:
            raise HTTPException(status_code=400, detail="添加备份计划失败，请检查Cron表达式格式")
        
        return {
            "status": "success",
            "message": "备份计划添加成功",
            "backup_type": backup_type,
            "cron_expression": cron_expression
        }
        
    except Exception as e:
        logger.error(f"添加备份计划失败: {e}")
        raise HTTPException(status_code=500, detail=f"添加备份计划失败: {str(e)}")


@router.delete("/schedule/remove/{job_id}", dependencies=[Depends(require_admin)])
async def remove_schedule(job_id: str) -> Dict[str, Any]:
    """
    移除备份计划
    
    Args:
        job_id: 任务ID
    
    Returns:
        Dict: 移除结果
    """
    try:
        scheduler = get_backup_scheduler()
        success = scheduler.remove_backup_job(job_id)
        
        if not success:
            raise HTTPException(status_code=404, detail=f"任务 {job_id} 不存在")
        
        return {
            "status": "success",
            "message": "备份计划移除成功",
            "job_id": job_id
        }
        
    except Exception as e:
        logger.error(f"移除备份计划失败: {e}")
        raise HTTPException(status_code=500, detail=f"移除备份计划失败: {str(e)}")


@router.get("/schedule/status", dependencies=[Depends(require_admin)])
async def get_scheduler_status() -> Dict[str, Any]:
    """
    获取调度器状态
    
    Returns:
        Dict: 调度器状态信息
    """
    try:
        scheduler = get_backup_scheduler()
        status = scheduler.get_status()
        
        return {
            "status": "success",
            "scheduler_info": status
        }
        
    except Exception as e:
        logger.error(f"获取调度器状态失败: {e}")
        raise HTTPException(status_code=500, detail=f"获取调度器状态失败: {str(e)}")


@router.post("/schedule/start", dependencies=[Depends(require_admin)])
async def start_scheduler() -> Dict[str, Any]:
    """
    启动备份调度器
    
    Returns:
        Dict: 启动结果
    """
    try:
        scheduler = get_backup_scheduler()
        scheduler.start()
        
        return {
            "status": "success",
            "message": "备份调度器已启动"
        }
        
    except Exception as e:
        logger.error(f"启动备份调度器失败: {e}")
        raise HTTPException(status_code=500, detail=f"启动备份调度器失败: {str(e)}")


@router.post("/schedule/stop", dependencies=[Depends(require_admin)])
async def stop_scheduler() -> Dict[str, Any]:
    """
    停止备份调度器
    
    Returns:
        Dict: 停止结果
    """
    try:
        scheduler = get_backup_scheduler()
        scheduler.stop()
        
        return {
            "status": "success",
            "message": "备份调度器已停止"
        }
        
    except Exception as e:
        logger.error(f"停止备份调度器失败: {e}")
        raise HTTPException(status_code=500, detail=f"停止备份调度器失败: {str(e)}")


@router.get("/status", dependencies=[Depends(require_admin)])
async def get_backup_system_status() -> Dict[str, Any]:
    """
    获取备份系统整体状态
    
    Returns:
        Dict: 系统状态信息
    """
    try:
        manager = get_backup_manager()
        scheduler = get_backup_scheduler()
        
        # 获取备份统计信息
        backups = await list_available_backups()
        
        # 统计各状态的备份数量
        status_counts = {}
        for record in backups:
            status = record["status"]
            status_counts[status] = status_counts.get(status, 0) + 1
        
        return {
            "status": "success",
            "backup_manager": {
                "initialized": manager._initialized,
                "active_backups": len(manager._active_backups),
                "backup_history_count": len(manager._backup_history)
            },
            "scheduler": scheduler.get_status(),
            "backup_statistics": {
                "total": len(backups),
                "by_status": status_counts,
                "latest_backup": backups[0] if backups else None
            }
        }
        
    except Exception as e:
        logger.error(f"获取备份系统状态失败: {e}")
        raise HTTPException(status_code=500, detail=f"获取备份系统状态失败: {str(e)}")


# 导入必要的模块
import os
import shutil